import os
import shutil
import tempfile

from oriolus.pith.archivers.zip import ZipError
from oriolus.pith.archivers.factory import PacketExtractorFactory, PacketExtractorFactoryError
from oriolus.pith.packer.packer import Packer

class RenamerError(Exception):
    def __init__(self, message):
        Exception.__init__(self, message)

class Renamer:
    def __init__(self, cache_path = None):
        if not cache_path:             
            self.cache_path = tempfile.mktemp()
        else:
            self.cache_path = cache_path
        
    def rename(self, packet_path, new_packet_path = None):
        if new_packet_path and (not os.path.exists(new_packet_path)):
            raise RenamerError("Output folder '%s' does not exists." % new_packet_path)
        
        if not os.path.exists(self.cache_path):
            os.makedirs(self.cache_path)
        
        if os.path.isdir(packet_path):
            for root, dirs, files in os.walk(packet_path):
                for dir in dirs:
                    if dir.startswith("."):
                        dirs.remove(dir)
                        
                for name in files:
                    if not name.startswith("."):
                        iter_packet_path = os.path.join(packet_path, name)
                        self.__rename_file(iter_packet_path, new_packet_path)
                    
        elif os.path.isfile(packet_path):
            self.__rename_file(packet_path, new_packet_path)
        else:
            raise RenamerError("Packet path is unknown object.")
            
        if os.path.exists(self.cache_path):
            shutil.rmtree(self.cache_path)

    def __rename_file(self, packet_path, new_packet_path):
        try:
            archiver = PacketExtractorFactory().get_extractor(packet_path)
            archiver.extract(packet_path, self.cache_path)
        except PacketExtractorFactoryError, message:
            raise RenamerError(message)
        except ZipError, message:
            raise RenamerError(message)
        
        packer = Packer()
        new_packet_name = packer.get_filename(self.cache_path)

        if new_packet_path:
            new_packet_path = os.path.join(new_packet_path, new_packet_name)
            shutil.copy(packet_path, new_packet_path)
        else:
            base_dir = os.path.dirname(packet_path)
            new_packet_path = os.path.join(base_dir, new_packet_name)
            shutil.move(packet_path, new_packet_path)
        